// Content script
// Author: Chaitanya Gharpure (chaitanyag@google.com)
// YouTube Access

var port;
var playerReady;
var ytplayer;
var checkYTReadyTimer;
var resultArr = [];
var currSelection;  // Currently selected video
var resultPos = -1; // Current index in the result list
var powerkey;
var titleList = []; // Array to hold titles
var currTimeElem, currInfoElem, currImageElem;
var timeElem, infoElem, imageElem;

function init() {
  // Connect to the extension
  port = chrome.extension.connect();
  port.onMessage.addListener(onMessage);

  // Parse the video Id from the URL, if any. If it is a
  // video URL, store it in the extension and redirect page
  // to www.youtube.com
  var tokens = (window.location + '').split(/watch\?v=|\&/g);
  if (tokens.length > 1) {  // If video Id is present, store it
    port.postMessage({cmd: 'storeId', videoid: tokens[1],
        time: new Date().getTime()});
    window.location = 'http://www.youtube.com';
    return;
  } else { 
    port.postMessage({cmd: 'overlay'});
  }
}

function initOverlay(html) {
  // place holder for HTML content
  var overlayParent = document.getElementById('overlay_parent');
  if (!overlayParent) {
    overlayParent = document.createElement('div');
    overlayParent.id = 'overlay_parent';
    document.body.appendChild(overlayParent);
  }
  // Set HTML sent by the extension
  overlayParent.innerHTML = html;
  insertYTPlayer();
  initPowerKey();
  document.getElementById('query').focus();
  document.addEventListener('scroll', function() {
      window.scroll(0,0);
    }, true);
  currTimeElem = document.getElementById('curr_video_time');
  currInfoElem = document.getElementById('curr_video_info');
  currImageElem = document.getElementById('curr_video_image');
  timeElem = document.getElementById('video_time');
  infoElem = document.getElementById('video_info');
  imageElem = document.getElementById('video_image');
}

function insertYTPlayer() {
  // Lets Flash from another domain call JavaScript
  var params = { allowScriptAccess: "always" };
  // The element id of the Flash embed
  var atts = { id: "myytplayer" };
  // All of the magic handled by SWFObject (http://code.google.com/p/swfobject/)
  swfobject.embedSWF("http://www.youtube.com/apiplayer?" +
                     "&enablejsapi=1&playerapiid=player1", 
                     "videoDiv", "480", "295", "8", null, null, params, atts);
  ytplayer = document.getElementById('myytplayer');
  // A hack, since onYouTubePlayerReady is not getting called in extensions
  checkYTReadyTimer = window.setInterval(function() {
        if (ytplayer.getPlayerState) {
          clearInterval(checkYTReadyTimer);
          onYouTubePlayerReady();
        }
      }, 100);
}

function initPowerKey() {
  powerkey = new PowerKey('search');
  powerkey.attachHandlerAndListen(document.getElementById('query'),
      'keyup', null, search_map);
  powerkey.attachHandlerAndListen(document.getElementById('query'),
      'focus', onGotoSearch, null);
  powerkey.attachHandlerAndListen(document.getElementById('query'),
      'blur', onGotoBrowse, null);
  powerkey.attachHandlerAndListen(document.getElementById('bg'),
      'keyup', null, browse_map);
  powerkey.attachHandlerAndListen(document, 'keyup', null,
      document_map);
  powerkey.attachHandlerAndListen(document, 'keydown', null,
      prevent_default_map);
  powerkey.setBrowseCallback(function(text, index) {
        if (index >= 0) {
          currSelection = resultArr[index];
          resultPos = index;
          updateVideoDisplay();
        }
      });
}

function onYouTubePlayerReady(playerid) {
  port.postMessage({cmd: 'checkStore'});
  playerReady = true;
};

function onSearch() {
  port.postMessage({
      cmd: 'search',
      value: document.getElementById('query').value
    });
  onGotoBrowse();
}

function onGotoBrowse() {
  document.getElementById('bg').focus();
  powerkey.context = 'browse';
}

function onGotoSearch() {
  document.getElementById('query').focus();
  powerkey.context = 'search';
}

function onPlay() {
  if (ytplayer && currSelection) {
    console.log('Playing: ' + currSelection.videoId);
    ytplayer.loadVideoById(currSelection.videoId, 0);
    updateCurrentVideoDisplay(0);
    startUIClock();
  }
}

function onPlayPause() {
  if (ytplayer && playerReady) {
    if (ytplayer.getPlayerState() == 1) {
      ytplayer.pauseVideo();
      stopUIClock();
    } else if (ytplayer.getPlayerState() != -1) {
      ytplayer.playVideo();
      updateCurrentVideoDisplay(0);
      startUIClock();
    }
  }
}

function onFwd() {
  if (ytplayer && playerReady && ytplayer.getPlayerState() != -1) {
    var newTime =
        Math.min(ytplayer.getCurrentTime() + 3, ytplayer.getDuration());
    ytplayer.seekTo(newTime, true);
  }
}

function onBack() {
  if (ytplayer && playerReady && ytplayer.getPlayerState() != -1) {
    var newTime = Math.max(ytplayer.getCurrentTime() - 3, 0);
    ytplayer.seekTo(newTime, true);
  }
}

function onVolumeUp() {
  if (ytplayer && playerReady) {
    ytplayer.setVolume(Math.min(ytplayer.getVolume() + 5, 100));
  }
}

function onVolumeDown() {
  if (ytplayer && playerReady) {
    ytplayer.setVolume(Math.max(ytplayer.getVolume() - 5, 0));
  }
}

function onNextResult() {
  resultPos = (resultPos + 1) == resultArr.length ? 0 : resultPos + 1;
  currSelection = resultArr[resultPos];
  updateVideoDisplay();
}

function onPrevResult() {
  resultPos = (resultPos - 1) < 0 ? resultArr.length - 1 : resultPos - 1;
  currSelection = resultArr[resultPos];
  updateVideoDisplay();
}

function preventDefault(evt) {
  if (! (evt.target instanceof HTMLInputElement))
    evt.preventDefault();
}

function onMessage(msg) {
  if (msg.overlay) {
    initOverlay(msg.overlay);
  } else if (msg.searchResult) {
    onSearchResult(msg.searchResult);
  } else if (msg.storeVideo) {
    currSelection = {};
    currSelection.videoId = msg.storeVideo.id;
    currSelection.title = msg.storeVideo.entry.title.$t;
    currSelection.duration =
          msg.storeVideo.entry.media$group.yt$duration.seconds;
    currSelection.imageUrl =
          msg.storeVideo.entry.media$group.media$thumbnail[0].url;
    currSelection.author = msg.storeVideo.entry.author[0].name.$t;
    currSelection.viewCount = msg.storeVideo.entry.yt$statistics.viewCount;
    onPlay();
  }
}

function onCompletion(completion, index, id, args) {
  currSelection = resultArr[index];
  resultPos = index;
  onGotoBrowse();
  onPlay();
}

function onShowPowerKey() {
  powerkey.updateCompletionField('visible');
}

// Parse the search results in the form of JSON, and store
// the result details in an array.
function onSearchResult(result) {
  resultArr = [];
  titleList = [];
  result = unescape(result);
  var resultObj = eval('(' + result + ')');
  var entries = resultObj.feed.entry;
  for (var i = 0, entry; entry = entries[i]; i++) {
    var res = {};
    try {
      res.title = entry.title.$t;
      res.descp = entry.media$group.media$description.$t;
      res.url = entry.media$group.media$player.url +
          '&enablejsapi=1&version=3';
      res.videoId = entry.media$group.yt$videoid.$t;
      res.duration = entry.media$group.yt$duration.seconds;
      res.imageUrl = entry.media$group.media$thumbnail[0].url;
      res.author = entry.author[0].name.$t;
      res.viewCount = entry.yt$statistics.viewCount;
    } catch(err) {
      console.log(err);
    }
    resultArr.push(res);
    titleList.push(res.title + ' - ' + res.videoId);
  }
  powerkey.createCompletionField(document.body, 50, onCompletion, null, titleList);
  powerkey.setAutoHideCompletionField(true);
  currSelection = resultArr[0];
  resultPos = 0;
}

function updateCurrentVideoDisplay(currPlayTime) {
  if (currSelection) {
    currInfoElem.textContent = currSelection.title;
    currTimeElem.textContent = formatTime(currPlayTime) + ' / ' +
        formatTime(currSelection.duration);
    currImageElem.src = currSelection.imageUrl;
  } else {
    currInfoElem.textContent = 'No video selected.';
    currTimeElem.textContent = '00:00:00 / 00:00:00';
    currImageElem.src = '';
  }
}

function updateVideoDisplay() {
  if (resultArr.length > 0) {
    infoElem.textContent = resultArr[resultPos].title;
    timeElem.textContent = formatTime(resultArr[resultPos].duration);
    imageElem.src = resultArr[resultPos].imageUrl;
  } else {
    infoElem.textContent = 'List Empty.';
    timeElem.textContent = '';
    imageElem.src = '';
  }
}

function startUIClock() {
  uiClockTimer = window.setInterval(function() {
        if (ytplayer && ytplayer.getPlayerState() == 1) {
          currTimeElem.textContent = 'Time: ' +
              formatTime(ytplayer.getCurrentTime()) + " / " +
              formatTime(ytplayer.getDuration());
        }
      }, 250);
}

function stopUIClock() {
  clearInterval(uiClockTimer);
}

function formatTime(totalsecs) {
  totalsecs = Math.floor(totalsecs);
  var mins = Math.floor(totalsecs / 60);
  var secs = totalsecs % 60;
  var hours = Math.floor(mins / 60);
  var mins = mins % 60;
  return ((hours  < 10 ? '0' + hours : hours) + ':' +
          (mins < 10 ? '0' + mins : mins) + ':' +
          (secs < 10 ? '0' + secs : secs));
}

// Action map for the search text field.
var search_map = {
  '27': {'search' : ['browse', onGotoBrowse]}, // ESC
  '13': {'search': ['browse', onSearch]}, //Enter
};

// Action map for the browse mode.
var browse_map = {
  '13': {'browse': ['browse', onPlay]}, // Enter
  '40': {'browse': ['browse', onNextResult]}, // Down arrow
  '38': {'browse': ['browse', onPrevResult]}, // up arrow
  '37': {'browse': ['browse', onBack]}, // left arrow
  '39': {'browse': ['browse', onFwd]}, // right arrow
  '189': {'browse': ['browse', onVolumeDown]}, // -
  '187': {'browse': ['browse', onVolumeUp]}, // =
  '191': {'browse': ['search', onGotoSearch]}, // '/'
  '32': {'browse': ['browse', onPlayPause]}, // space
  '190': {'browse': ['browse', onShowPowerKey]} // '.'
};

var document_map = {
  '27': {'browse' : ['browse', onGotoBrowse]}, // ESC
};

// This key binding presents default actions of scrolling the page
// when up/down/left/right/space keys are pressed.
var prevent_default_map = {
  '32,37,38,39,40': {'*': ['*', preventDefault]},
};

init();
